#ifndef __GPUFB_H
#define __GPUFB_H

#include <asm/page.h>

struct graphic_layer_table {
        u32 img_src_addr;               /* graphic layer table word 0 */
        u32 width:      10,             /* graphic layer table word 1 */
            height:     10,
            angle:      9,
            transparent:1,
            reserved0:  1,
            end_layer:  1;
        u32 img_x:      10,							/* graphic layer table word 2 */
        	  img_y:      10,
        	  scale:      4,
            reserved1:  4,
            direction:  2,
            draw:       2;             
        u32 center_x:   11,							/* graphic layer table word 3 */
        	  center_y:   11,
        	  slope:      10;             
};

struct gpufb_reg {
        struct graphic_layer_table glt;
        u32 layer_index;
        u32 control;
        u32 command;
        u32 lcd_vertical;               /* LCD vertical parameter: tvs tvp tve */
        u32 lcd_horizontal;             /* LCD horizontal parameter: ths thp the */
        u32 lcd_resolution;             /* LCD resolution parameter: tvd thd */
        u32 status;
        u32 fb_current_pos;             /* Framebuffer current position */
        u32 tp_control;                 /* Transparent RGB value */
        u32 fb_base0;                   /* Framebuffer base 0 */
        u32 fb_base1;                   /* Framebuffer base 1 */
        u32 vga2_fb_base;               /* Framebuffer base address for VGA controller#2 */
};

struct videoin_reg {
        u32 vi_fb_base;
        u32 vi_frame_size;
        u32 vi_control;
        u32 vi_res;
        u32 vi_sync_timing_blank;
        u32 vi_sync_timing_data;
};

struct gpufb_par {
	struct fb_info *fb;
	volatile struct gpufb_reg __iomem *gpu_regs;  /* Pointer to GPU register set */
	volatile struct videoin_reg __iomem *vi_regs; /* Pointer to Video In register set */
};


#define GPU_REG_BASE          (void __iomem *)na_graphic_0
#define GPU_IRQ               na_graphic_0_irq
#define GPU_FB_SIZE           (0x00200000)
#define GPU_FB_ORDER          get_order(GPU_FB_SIZE) /* (GPU_FB_SIZE/PAGE_SIZE) >> ? = 1 */
#define GPU_FB_PGSIZE         (0x00100000)
#define GPU_REG_LEN           sizeof(struct gpufb_reg)

#define VIDEOIN_REG_BASE      (void __iomem *)na_videoin_0
#define VIDEOIN_REG_LEN       sizeof(struct videoin_reg)
#define VIDEOIN_FB_BASE       na_sdram_1
#define VIDEOIN_FB_SIZE       GPU_FB_SIZE

#define BPP_16	              16
#define BPP_24                24
#define MAX_LAYER_INDEX	      32

#define GPU_REG_CONTROL_LCD_EN    0x01
#define GPU_REG_CONTROL_MENU_EN   0x02
#define GPU_REG_CONTROL_VIDEO_EN  0x04
#define GPU_REG_CONTROL_GPU_EN    0x08
#define GPU_REG_CONTROL_INT_EN    0x10

#define VI_REG_CONTROL_MODE       0x00
#define VI_REG_CONTROL_INV_DCLK   0x04
#define VI_REG_CONTROL_INV_DE     0x08
#define VI_REG_CONTROL_INV_HS     0x10
#define VI_REG_CONTROL_INV_VS     0x20
#define VI_REG_CONTROL_INV_F      0x40
#define VI_REG_CONTROL_INTERLACE  0x80
#define VI_REG_CONTROL_EN         0x80000000

#define REG_COMMAND_WRDISP    0x00	/* Tell GPU to write to display page (Data from GLT) */
#define REG_COMMAND_WRBUFSW   0x01	/* Tell GPU to write to buffer page, do switch (Data from GLT)*/
#define REG_COMMAND_WRBUF     0x02  /* Tell GPU to write to buffer page, do NOT switch (Data from GLT)*/
#define REG_COMMAND_SW        0x03  /* Tell GPU to switch display and buffer page */
#define REG_COMMAND_CAPDISP   0x04  /* Tell GPU to capture data on display page to specified address */
#define REG_COMMAND_CAPBUF    0x05  /* Tell GPU to capture data on buffer page to specified address */

#define GLT_DRAW_IMAGE        0x00
#define GLT_DRAW_RECT_FRAME   0x02
#define GLT_DRAW_RECT_FILLED  0x03

/* Transparent Rate for Menu and Video in*/
#define M50V50     0x0
#define M25V75     0x1
#define M12_5V87_5 0x2
#define M0V100     0x3
#define V50M50     0x4
#define M75V25     0x5
#define M87_5V12_5 0x6
#define M100V0     0x7

/* GPU Macros */
#define GET_CTL(x)       			(reg_readl((u32)&x->control))
#define SET_CTL(x, v)    			reg_writel((u32)&x->control, v)

#define GET_CMD(x)       			(reg_readl((u32)&x->command))
#define SET_CMD(x, v)    			reg_writel((u32)&x->command, v)

#define GET_LCDV(x)           (reg_readl((u32)&x->lcd_vertical))
#define GET_TVS(x)            ((reg_readl((u32)&x->lcd_vertical) >> 20) & 0x03ff)
#define GET_TVP(x)            ((reg_readl((u32)&x->lcd_vertical) >> 10) & 0x03ff)
#define GET_TVE(x)            (reg_readl((u32)&x->lcd_vertical) & 0x03ff)

#define GET_LCDH(x)           (reg_readl((u32)&x->lcd_horizontal))
#define GET_THS(x)            ((reg_readl((u32)&x->lcd_horizontal) >> 20) & 0x03ff)
#define GET_THP(x)            ((reg_readl((u32)&x->lcd_horizontal) >> 10) & 0x03ff)
#define GET_THE(x)            (reg_readl((u32)&x->lcd_horizontal) & 0x03ff)

#define GET_LCDR(x)           (reg_readl((u32)&x->lcd_resolution))
#define GET_TVD(x)            ((reg_readl((u32)&x->lcd_resolution) >> 10) & 0x03ff)
#define GET_THD(x)            (reg_readl((u32)&x->lcd_resolution) & 0x03ff)

#define SET_LCDV(x, s, p, e)  reg_writel((u32)&x->lcd_vertical, \
                                         (((s) & 0x03ff) << 20) | \
                                         (((p) & 0x03ff) << 10) | \
                                         ((e) & 0x03ff))
#define SET_LCDH(x, s, p, e)  reg_writel((u32)&x->lcd_horizontal, \
                                         (((s) & 0x03ff) << 20) | \
                                         (((p) & 0x03ff) << 10) | \
                                         ((e) & 0x03ff))
#define SET_LCDR(x, v, h)     reg_writel((u32)&x->lcd_resolution, \
                                         (((v) & 0x03ff) << 10) | \
                                         ((h) & 0x03ff))

#define GET_GLTIDX(x)       	(reg_readl((u32)&x->layer_index))
#define SET_GLTIDX(x, v)    	reg_writel((u32)&x->layer_index, v)

#define GET_STAT(x)       		(reg_readl((u32)&x->status))
#define GET_DISP_PAGE(x)      (reg_readl((u32)&x->fb_current_pos))

#define GET_GLT(to, x)      	to[0] = reg_readl((u32)&(x->glt)); \
															to[1] = reg_readl((u32)((u8 *)&(x->glt) + 4)); \
															to[2] = reg_readl((u32)((u8 *)&(x->glt) + 8)); \
															to[3] = reg_readl((u32)((u8 *)&(x->glt) + 12))
#define SET_GLT(from, x)      reg_writel((u32)&(x->glt), *((u32 *)&from)); \
															reg_writel((u32)((u8 *)&(x->glt) + 4), *((u32 *)((u8 *)&from + 4))); \
															reg_writel((u32)((u8 *)&(x->glt) + 8), *((u32 *)((u8 *)&from + 8))); \
															reg_writel((u32)((u8 *)&(x->glt) + 12), *((u32 *)((u8 *)&from + 12)))
			
#define GET_TP_RATE(x)        ((reg_readl((u32)&x->tp_control) >> 16) & 0x7)
#define GET_TP_VALUE(x)       (reg_readl((u32)&x->tp_control) & 0x0000ffff)

#define SET_TP(x, r, v)       reg_writel((u32)&x->tp_control, ((r) << 16) | ((v) & 0x0000ffff))

#define GET_FB_BASE0(x)       (reg_readl((u32)&x->fb_base0))
#define SET_FB_BASE0(x, v)    reg_writel((u32)&x->fb_base0, v)

#define GET_FB_BASE1(x)       (reg_readl((u32)&x->fb_base1))
#define SET_FB_BASE1(x, v)    reg_writel((u32)&x->fb_base1, v)

#define GET_FB_VGA2_BASE(x)       (reg_readl((u32)&x->vga2_fb_base))
#define SET_FB_VGA2_BASE(x, v)    reg_writel((u32)&x->vga2_fb_base, v)

/* Video-In Macros */
#define GET_VI_BASE(x)        (reg_readl((u32)&x->vi_fb_base))
#define SET_VI_BASE(x, v)     reg_writel((u32)&x->vi_fb_base, v)

#define GET_VI_HEIGHT(x)      ((reg_readl((u32)&x->vi_frame_size) >> 10) & 0x03ff)
#define GET_VI_WIDTH(x)       (reg_readl((u32)&x->vi_frame_size) & 0x03ff)
#define SET_VI_FRM_SZ(x, w, h) reg_writel((u32)&x->vi_frame_size, \
                                          (((h) & 0x03ff) << 10) | ((w) & 0x03ff))

#define GET_VI_CTRL(x)        (reg_readl((u32)&x->vi_control))
#define SET_VI_CTRL(x, v)     reg_writel((u32)&x->vi_control, v)

#define GET_VI_LINES(x)       ((reg_readl((u32)&x->vi_res) >> 10) & 0x03ff)
#define GET_VI_PIXELS(x)      (reg_readl((u32)&x->vi_res) & 0x03ff)

#define SET_VI_SYNC_TIMING_BL(x, v)  reg_writel((u32)&x->vi_sync_timing_blank, v)
#define SET_VI_SYNC_TIMING_DT(x, v)  reg_writel((u32)&x->vi_sync_timing_data, v)

/* GPU FB ioctl */
#define FBIOCTL_SET_CTRL        0x4620
#define FBIOCTL_GET_CTRL        0x4621
#define FBIOCTL_SET_CMD         0x4622
#define FBIOCTL_GET_CMD         0x4623
#define FBIOCTL_SET_LCDV        0x4624
#define FBIOCTL_GET_LCDV        0x4625
#define FBIOCTL_SET_LCDH        0x4626
#define FBIOCTL_GET_LCDH        0x4627
#define FBIOCTL_SET_LCDRES      0x4628
#define FBIOCTL_GET_LCDRES      0x4629
#define FBIOCTL_GET_STATUS      0x462A
#define FBIOCTL_SET_GLTIDX      0x462B
#define FBIOCTL_GET_GLTIDX      0x462C
#define FBIOCTL_SET_GLT         0x462D
#define FBIOCTL_GET_GLT         0x462E
#define FBIOCTL_GET_DISP_ADDR   0x462F
#define FBIOCTL_GET_BUF_ADDR    0x4630
#define FBIOCTL_SET_TPRATE      0x4631
#define FBIOCTL_GET_TPRATE      0x4632
#define FBIOCTL_SET_TPVALUE     0x4633
#define FBIOCTL_GET_TPVALUE     0x4634
#define FBIOCTL_SET_FBBASE0     0x4635
#define FBIOCTL_GET_FBBASE0     0x4636
#define FBIOCTL_SET_FBBASE1     0x4637
#define FBIOCTL_GET_FBBASE1     0x4638
#define FBIOCTL_SET_FBVGA2BASE  0x4639
#define FBIOCTL_GET_FBVGA2BASE  0x463A
#define FBIOCTL_GPU_WAIT        0x463B
/* Video In ioctl */
#define FBIOCTL_SET_VIBASE      0x4650
#define FBIOCTL_GET_VIBASE      0x4651
#define FBIOCTL_GET_VI_HEIGHT   0x4652
#define FBIOCTL_GET_VI_WIDTH    0x4653
#define FBIOCTL_SET_VI_FRMSZ    0x4654
#define FBIOCTL_SET_VI_CTRL     0x4655
#define FBIOCTL_GET_VI_CTRL     0x4656
#define FBIOCTL_GET_VI_LINE     0x4657
#define FBIOCTL_GET_VI_PIXEL    0x4658
#define FBIOCTL_SET_VI_SMTB     0x4659
#define FBIOCTL_GET_VI_SMTB     0x465A
#define FBIOCTL_SET_VI_SMTD     0x465B
#define FBIOCTL_GET_VI_SMTD     0x465C

/* From MicroWindows font_dbcs.c */
/* create 16 bit 5/6/5 format pixel from RGB triplet */
#define RGB2PIXEL565(r,g,b)	((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3))

/* return 8 bit r, g or b component of 5/6/5 16 bit pixelval*/
#define PIXEL565RED8(pixelval)          (((pixelval) >> 8) & 0xf8)
#define PIXEL565GREEN8(pixelval)        (((pixelval) >> 3) & 0xfc)
#define PIXEL565BLUE8(pixelval)         (((pixelval) << 3) & 0xf8)

#endif
